#include "redis.h"
#include <string.h>
#include <map>


int Redis::Get(const string& key, string& out)
{
	redisReply * reply = NULL;
	int32_t ret = 0;
	reply = redis_client_->redisCommand( "get %s", key.c_str() );
	if ( reply == NULL ) {


		ret = -1;
		return ret;
	}

	if ( reply->type == REDIS_REPLY_STRING && reply->str )
	{
		out = reply->str;
	}


	redis_client_->freeReply(reply);
	return ret;
}


int Redis::Smembers( const string& key, vector<string>& out )
{
	redisReply * reply = NULL;
	int32_t ret = 0;
	reply = redis_client_->redisCommand( "smembers %s", key.c_str() );
	if ( reply == NULL )
	{
		ret = -1;
		return ret;
	}
	if ( reply->type == REDIS_REPLY_ARRAY && reply->elements > 0 )
	{
		for( size_t i = 0; i < reply->elements; i++ )
		{
			out.push_back( reply->element[i]->str );
		}
	}


	redis_client_->freeReply(reply);
	return ret;
}

	int Redis::Scard( const string& key )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "scard %s", key.c_str() );
		if ( reply == NULL )
		{
			
		
	
			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER )
		{
			ret = reply->integer;
		}
		else if(REDIS_REPLY_NIL == reply->type)
		{
			ret = -3;
		}
		else
		{
		
			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;
	}

	int Redis::Sismember( const string& key, const string& value, bool& is_member)
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "sismember %s %s", key.c_str(), value.c_str() );
		if ( reply == NULL )
		{
	


			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER )
		{
			is_member = (bool)reply->integer;
		}
		else
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);

		return ret;
	}

	int Redis::Hgetall( const string& key, vector< pair<string,string> >& values )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "hgetall %s", key.c_str() );
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_ARRAY && reply->elements > 0 && reply->elements % 2 == 0 )
		{
			for( size_t i = 0; i < reply->elements; )
			{
				string field = reply->element[i]->str;
				string value = reply->element[i+1]->str;
				pair<string,string> kv = make_pair( field, value );
				values.push_back( kv );
				i += 2;
			}
		}
		
		redis_client_->freeReply(reply);
		return ret;
	}


	int Redis::Hgetall( const string& key, map<string,string>& values )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "hgetall %s", key.c_str() );
		if ( reply == NULL )
		{
	


			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_ARRAY && reply->elements > 0 && reply->elements % 2 == 0 )
		{
			for( size_t i = 0; i < reply->elements; )
			{
				string field = reply->element[i]->str;
				string value = reply->element[i+1]->str;
				pair<string,string> kv = make_pair( field, value );
				values.insert(kv);

				i += 2;
			}
		}


		redis_client_->freeReply(reply);
		return ret;
	}

	int Redis::Hget( const string& key, const string& field, string& value )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "hget %s %s", key.c_str(), field.c_str() );
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_STRING )
		{
			value = reply->str;
		}
	


		redis_client_->freeReply(reply);
		return ret;
	}

	int Redis::Hexists( const string& key, const string & field )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "hexists %s %s", key.c_str(), field.c_str() );
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER )
		{
			ret = reply->integer;
		}
		else
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;

	}

	int Redis::Set(const string& key, const string& value)
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "set %s %s", key.c_str(), value.c_str());
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( !(reply->type == REDIS_REPLY_STATUS && strcmp(reply->str,"OK") == 0 ) )
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;
	}

	int Redis::Sadd( const string& key, const string& value )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "sadd %s %s", key.c_str(), value.c_str());
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		else if(reply->type != REDIS_REPLY_INTEGER)
		{
			ret = -2;
		}
		else
		{
			if(reply->integer != 1)
			{
				ret = -3;
			}
		}

		if ( reply->type != REDIS_REPLY_INTEGER || reply->integer != 1 )
		{

		}
		redis_client_->freeReply(reply);
		return ret;
	}

	int Redis::Srem( const string& key, const string& value )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "srem %s %s", key.c_str(), value.c_str());
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER  )
		{
			if( reply->integer == 0 )
			{

				ret = -3;
			}
		}
		else
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;
	}

	int Redis::Hmset( const string& key, const vector< pair<string,string> >& values )
	{

		redisReply * reply = NULL;
		int32_t ret = 0;
		


		reply = HmSetSelectWithParaCount(key, values);
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type != REDIS_REPLY_STATUS || strcmp(reply->str, "OK") != 0 )
		{


			ret = -2;
		}


		redis_client_->freeReply(reply);
		return ret;
	}

	int Redis::Hset( const string& key, const string& field, const string& value )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;

		reply = redis_client_->redisCommand( "hset %s %s %s", key.c_str(), field.c_str(), value.c_str() );
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type != REDIS_REPLY_INTEGER )
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;
	}

	int Redis::Hdel( const string& key, const string& field )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "hdel %s %s", key.c_str(), field.c_str());
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER  )
		{
			if( reply->integer == 0 )
			{
				ret = -3;
			}
		}
		else
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;
	}

	int Redis::DelKey( const string& key )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "del %s", key.c_str());
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER  )
		{
			if( reply->integer == 0 )
			{
				ret = -3;
			}
		}
		else
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;

	}

	int Redis::Publish( const string& channel, const string& value )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "publish %s %s", channel.c_str(), value.c_str());
		if ( reply == NULL )
		{
			ret = -1;
			return ret;
		}
		if ( reply->type != REDIS_REPLY_INTEGER  )
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;
	}

	int Redis::Incr( const string& key, int n )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "incrby %s %d", key.c_str(), n);
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER  )
		{
			if( reply->integer == 0 )
			{
				ret = -3;
			}
		}
		else
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;

	}


	int Redis::Incr( const string& key, int n, int64_t& ret_val)
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "incrby %s %d", key.c_str(), n);
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER  )
		{
			if( reply->integer == 0 )
			{
				ret = -3;
			}
			else
			{
				ret_val = reply->integer;
			}
		}
		else
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;

	}


	int Redis::HIncrBy( const string& key, const string& field, int n )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "hincrby %s %s %d", key.c_str(), field.c_str(), n);
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER  )
		{
			if( reply->integer == 0 )
			{
				ret = -3;
			}
		}
		else
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;

	}


	int Redis::HIncrBy( const string& key, const string& field, int n, int64_t& ret_val)
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "hincrby %s %s %d", key.c_str(), field.c_str(), n);
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER  )
		{
			if( reply->integer == 0 )
			{
				ret = -3;
			}
			else
			{
				ret_val = reply->integer;
			}
		}
		else
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;

	}

	int Redis::Scard( const string& key, uint32_t& count )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "scard %s", key.c_str() );
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER )
		{
			count = reply->integer;
		}
		else if(REDIS_REPLY_NIL == reply->type)
		{
			ret = -3;
		}
		else
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;
	}


	int Redis::Hexists( const string& key, const string & field, bool& exist )
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "hexists %s %s", key.c_str(), field.c_str() );
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_INTEGER )
		{
			if( reply->integer == 1 )
			{
				exist = true;
			}
			else
			{
				exist = false;
			}
		}
		else
		{

			ret = -2;
		}
		redis_client_->freeReply(reply);
		return ret;
	}


	int Redis::Keys(const string& key, vector<string>& out)
	{
		redisReply * reply = NULL;
		int32_t ret = 0;
		reply = redis_client_->redisCommand( "keys %s", key.c_str() );
		if ( reply == NULL )
		{



			ret = -1;
			return ret;
		}
		if ( reply->type == REDIS_REPLY_ARRAY && reply->elements > 0 )
		{
			for( size_t i = 0; i < reply->elements; i++ )
			{
				out.push_back( reply->element[i]->str );
			}
		}
		
		redis_client_->freeReply(reply);
		return ret;
	}

	string Redis::TransferredStringMeaning(const string& src)
	{
		const static string kRpOrg = "\"";
		const static string kRpDst = "\\\"";

		string temp_src = src;

		string::size_type pos=0;
		string::size_type srclen = kRpOrg.size();
		string::size_type dstlen = kRpDst.size();
		while( (pos=temp_src.find(kRpOrg, pos)) != string::npos)
		{
			temp_src.replace(pos, srclen, kRpDst);
			pos += dstlen;
		}

		return temp_src;
	}


	redisReply* Redis::HmSetSelectWithParaCount( const string& key, const vector< pair<string,string> >& values )
	{
	
		string format;
		for( uint32_t i = 0; i < values.size(); i++ )
		{
			if(values[i].first.empty() || values[i].second.empty())
			{
				continue;
			}
			//    format += "'" + TransferredStringMeaning(values[i].first) + "' ";
			format += " " + values[i].first;
			format += " \"" + TransferredStringMeaning(values[i].second) + "\"";
		}

		switch (values.size())
		{
			case 1:
				return redis_client_->redisCommand( "hmset %s %s %s", key.c_str(), values[0].first.c_str(), values[0].second.c_str());
			case 2:
				return redis_client_->redisCommand( "hmset %s %s %s %s %s", key.c_str(), values[0].first.c_str(), values[0].second.c_str()
						, values[1].first.c_str(), values[1].second.c_str());
			case 3:
				return redis_client_->redisCommand( "hmset %s %s %s %s %s %s %s", key.c_str(), values[0].first.c_str(), values[0].second.c_str()
						, values[1].first.c_str(), values[1].second.c_str()
						, values[2].first.c_str(), values[2].second.c_str());
			case 4:
				return redis_client_->redisCommand( "hmset %s %s %s %s %s %s %s %s %s", key.c_str(), values[0].first.c_str(), values[0].second.c_str()
						, values[1].first.c_str(), values[1].second.c_str()
						, values[2].first.c_str(), values[2].second.c_str()
						, values[3].first.c_str(), values[3].second.c_str()
						);
			case 5:
				return redis_client_->redisCommand( "hmset %s %s %s %s %s %s %s %s %s %s %s", key.c_str(), values[0].first.c_str(), values[0].second.c_str()
						, values[1].first.c_str(), values[1].second.c_str()
						, values[2].first.c_str(), values[2].second.c_str()
						, values[3].first.c_str(), values[3].second.c_str()
						, values[4].first.c_str(), values[4].second.c_str()
						);
			case 6:
				return redis_client_->redisCommand( "hmset %s %s %s %s %s %s %s %s %s %s %s %s %s", key.c_str(), values[0].first.c_str(), values[0].second.c_str()
						, values[1].first.c_str(), values[1].second.c_str()
						, values[2].first.c_str(), values[2].second.c_str()
						, values[3].first.c_str(), values[3].second.c_str()
						, values[4].first.c_str(), values[4].second.c_str()
						, values[5].first.c_str(), values[5].second.c_str()
						);
			case 7:
				return redis_client_->redisCommand( "hmset %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", key.c_str(), values[0].first.c_str(), values[0].second.c_str()
						, values[1].first.c_str(), values[1].second.c_str()
						, values[2].first.c_str(), values[2].second.c_str()
						, values[3].first.c_str(), values[3].second.c_str()
						, values[4].first.c_str(), values[4].second.c_str()
						, values[5].first.c_str(), values[5].second.c_str()
						, values[6].first.c_str(), values[6].second.c_str()
						);
			case 8:
				return redis_client_->redisCommand( "hmset %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", key.c_str(), values[0].first.c_str(), values[0].second.c_str()
						, values[1].first.c_str(), values[1].second.c_str()
						, values[2].first.c_str(), values[2].second.c_str()
						, values[3].first.c_str(), values[3].second.c_str()
						, values[4].first.c_str(), values[4].second.c_str()
						, values[5].first.c_str(), values[5].second.c_str()
						, values[6].first.c_str(), values[6].second.c_str()
						, values[7].first.c_str(), values[7].second.c_str()
						);
			case 9:
				return redis_client_->redisCommand( "hmset %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", key.c_str(), values[0].first.c_str(), values[0].second.c_str()
						, values[1].first.c_str(), values[1].second.c_str()
						, values[2].first.c_str(), values[2].second.c_str()
						, values[3].first.c_str(), values[3].second.c_str()
						, values[4].first.c_str(), values[4].second.c_str()
						, values[5].first.c_str(), values[5].second.c_str()
						, values[6].first.c_str(), values[6].second.c_str()
						, values[7].first.c_str(), values[7].second.c_str()
						, values[8].first.c_str(), values[8].second.c_str()
						);
			case 10:
				return redis_client_->redisCommand( "hmset %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", key.c_str(), values[0].first.c_str(), values[0].second.c_str()
						, values[1].first.c_str(), values[1].second.c_str()
						, values[2].first.c_str(), values[2].second.c_str()
						, values[3].first.c_str(), values[3].second.c_str()
						, values[4].first.c_str(), values[4].second.c_str()
						, values[5].first.c_str(), values[5].second.c_str()
						, values[6].first.c_str(), values[6].second.c_str()
						, values[7].first.c_str(), values[7].second.c_str()
						, values[8].first.c_str(), values[8].second.c_str()
						, values[9].first.c_str(), values[9].second.c_str()
						);
		

		}


		return NULL;
	}




